{
 "cells": [
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "## CNN\n",
    "CNN就是convolutional neural network，也就是卷积神经网络，用在图像处理中。\n",
    "\n",
    "## 卷积核\n",
    "卷积核是用来提取特征的，不同的卷积核，提取出图片的不同特征，相当于不再使用整张图片的所有像素点作为图片的特征了，而是提取出图片中最核心的部分，忽略掉一些无用的信息，从而减少运算量。\n",
    "\n",
    "## 池化层\n",
    "池化就是缩小图片，比如将图片缩小到原来的1/2，这样图片的分辨率变小，但是图片的语义信息不变，因此可以减少运算量。\n",
    "池化分为两种：\n",
    "1. 最大池化\n",
    "2. 平均池化"
   ],
   "id": "2528fc8bcfd7695"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "利用pytorch自动下载MNIST数据集\n",
    "\n",
    "MNIST数据集介绍：https://docs.ultralytics.com/zh/datasets/classify/mnist/"
   ],
   "id": "e2a1055260107c79"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-21T02:13:10.169800Z",
     "start_time": "2025-08-21T02:13:08.616894Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import matplotlib.pyplot as plt\n",
    "from torchvision import datasets\n",
    "\n",
    "# pytorch下载mnist数据集\n",
    "train_dataset = datasets.MNIST(root='./data/', train=True, download=True)\n",
    "test_dataset = datasets.MNIST(root='./data/', train=False, download=True)\n",
    "print(len(train_dataset))\n",
    "print(len(test_dataset))"
   ],
   "id": "6a8045e503437201",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "60000\n",
      "10000\n"
     ]
    }
   ],
   "execution_count": 1
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-21T02:13:31.918508Z",
     "start_time": "2025-08-21T02:13:31.900372Z"
    }
   },
   "cell_type": "code",
   "source": "train_dataset[0][0]",
   "id": "70d5050cc316e7bf",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<PIL.Image.Image image mode=L size=28x28>"
      ],
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAAAAABXZoBIAAABAklEQVR4AWIY1IBZSEiormO91LL/3+tBDmUBESAsx2ZlIxAMYj2ZFPj54kEQixFEMDAwGO7lh7L+JX1lePb+JpQHBkK3/4LAsW3fP4L5qETAnOy/f89yM2jPQhWHAD7GWX+jIEwYyQRjMHz6/5EhBcGFi0MB976/blAmFkr548MFOTD3Y8gHfvj7t1wSQxgKdHf9/TtNGsrBoARi//zdjSEKBz///nSAcuBhC+HrhZiyMFw7BOGgkoCpT3n69+/fX9tQRcE8iaK7oOA96QfmoRDiTldBUscCMQNJaDU4Vg4HcKLoAHHM1zwC6frSyg3iITDYtYGBDAzXN//t+YAQpyULAEUXXoDz1Y8qAAAAAElFTkSuQmCC",
      "image/jpeg": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/wAALCAAcABwBAREA/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/9oACAEBAAA/APAACzBVBJJwAO9dnp/wm8damu6Dw5dRjGf9IKw/+hkVPffCnWNJa7XVNV0Kxa1hErrNe/M2cnYqgElsAHpjkc1wlAODkV694W8c654t8M6n4TuvEctrrFw0cun3c0/lq+3AMJcDK5AyOeTkd+fPvGFn4gsvEtzF4m89tUG1ZJJjuMgUBVYN/EMKOe9YVXtK0bUtdvVs9LsZ7y4YgbIULYycZPoPc8V6lpfwh0/w7p66z8RdXj0y2z8llC4aWQ+mRn8lz9RXPfE3x1pvi46TYaPZTQadpMJghluWDSyrhQM9SMBe5Oc5NcBV7Tda1XRZJJNK1O8sXkG12tZ2iLD0JUjNQ3l9eahN517dT3MvTfNIXb16n6mq9Ff/2Q=="
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 2
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-21T02:13:33.996398Z",
     "start_time": "2025-08-21T02:13:33.991721Z"
    }
   },
   "cell_type": "code",
   "source": "train_dataset[0][1]",
   "id": "12da69b406742d69",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 3
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "直接通过transforms得到归一化后的图片张量数据集",
   "id": "aa6715b77bd2798f"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-21T02:14:46.813137Z",
     "start_time": "2025-08-21T02:14:46.749435Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from torchvision import datasets, transforms\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# pytorch下载mnist\n",
    "train_dataset = datasets.MNIST(root='./data/', train=True, transform=transforms.ToTensor(), download=True)\n",
    "test_dataset = datasets.MNIST(root='./data/', train=False, transform=transforms.ToTensor(), download=True)\n",
    "train_dataset[0][0].shape"
   ],
   "id": "def0631eb08602dc",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.Size([1, 28, 28])"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 9
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-21T02:14:49.057070Z",
     "start_time": "2025-08-21T02:14:49.049562Z"
    }
   },
   "cell_type": "code",
   "source": "train_dataset[0][0]",
   "id": "88941196ae23918b",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[[0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000],\n",
       "         [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000],\n",
       "         [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000],\n",
       "         [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000],\n",
       "         [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000],\n",
       "         [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000, 0.0118, 0.0706, 0.0706, 0.0706,\n",
       "          0.4941, 0.5333, 0.6863, 0.1020, 0.6510, 1.0000, 0.9686, 0.4980,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000],\n",
       "         [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.1176, 0.1412, 0.3686, 0.6039, 0.6667, 0.9922, 0.9922, 0.9922,\n",
       "          0.9922, 0.9922, 0.8824, 0.6745, 0.9922, 0.9490, 0.7647, 0.2510,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000],\n",
       "         [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.1922,\n",
       "          0.9333, 0.9922, 0.9922, 0.9922, 0.9922, 0.9922, 0.9922, 0.9922,\n",
       "          0.9922, 0.9843, 0.3647, 0.3216, 0.3216, 0.2196, 0.1529, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000],\n",
       "         [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0706,\n",
       "          0.8588, 0.9922, 0.9922, 0.9922, 0.9922, 0.9922, 0.7765, 0.7137,\n",
       "          0.9686, 0.9451, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000],\n",
       "         [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.3137, 0.6118, 0.4196, 0.9922, 0.9922, 0.8039, 0.0431, 0.0000,\n",
       "          0.1686, 0.6039, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000],\n",
       "         [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0549, 0.0039, 0.6039, 0.9922, 0.3529, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000],\n",
       "         [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.5451, 0.9922, 0.7451, 0.0078, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000],\n",
       "         [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0431, 0.7451, 0.9922, 0.2745, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000],\n",
       "         [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000, 0.1373, 0.9451, 0.8824, 0.6275,\n",
       "          0.4235, 0.0039, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000],\n",
       "         [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.3176, 0.9412, 0.9922,\n",
       "          0.9922, 0.4667, 0.0980, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000],\n",
       "         [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.1765, 0.7294,\n",
       "          0.9922, 0.9922, 0.5882, 0.1059, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000],\n",
       "         [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0627,\n",
       "          0.3647, 0.9882, 0.9922, 0.7333, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000],\n",
       "         [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.9765, 0.9922, 0.9765, 0.2510, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000],\n",
       "         [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.1804, 0.5098,\n",
       "          0.7176, 0.9922, 0.9922, 0.8118, 0.0078, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000],\n",
       "         [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000, 0.1529, 0.5804, 0.8980, 0.9922,\n",
       "          0.9922, 0.9922, 0.9804, 0.7137, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000],\n",
       "         [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0941, 0.4471, 0.8667, 0.9922, 0.9922, 0.9922,\n",
       "          0.9922, 0.7882, 0.3059, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000],\n",
       "         [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0902, 0.2588, 0.8353, 0.9922, 0.9922, 0.9922, 0.9922, 0.7765,\n",
       "          0.3176, 0.0078, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000],\n",
       "         [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0706, 0.6706,\n",
       "          0.8588, 0.9922, 0.9922, 0.9922, 0.9922, 0.7647, 0.3137, 0.0353,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000],\n",
       "         [0.0000, 0.0000, 0.0000, 0.0000, 0.2157, 0.6745, 0.8863, 0.9922,\n",
       "          0.9922, 0.9922, 0.9922, 0.9569, 0.5216, 0.0431, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000],\n",
       "         [0.0000, 0.0000, 0.0000, 0.0000, 0.5333, 0.9922, 0.9922, 0.9922,\n",
       "          0.8314, 0.5294, 0.5176, 0.0627, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000],\n",
       "         [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000],\n",
       "         [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000],\n",
       "         [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
       "          0.0000, 0.0000, 0.0000, 0.0000]]])"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 10
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-21T02:15:15.430092Z",
     "start_time": "2025-08-21T02:15:15.426526Z"
    }
   },
   "cell_type": "code",
   "source": "train_dataset[0][0].shape",
   "id": "1adcdbc9b7533684",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.Size([1, 28, 28])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 11
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-21T02:16:07.689023Z",
     "start_time": "2025-08-21T02:16:07.626898Z"
    }
   },
   "cell_type": "code",
   "source": "plt.imshow(train_dataset[0][0].view(-1, 28), cmap='gray')",
   "id": "4f1ce419-3cbd-482b-9bb4-9cc70f972e3e",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x10e404100>"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ],
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAaAAAAGdCAYAAABU0qcqAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjMsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvZiW1igAAAAlwSFlzAAAPYQAAD2EBqD+naQAAGaxJREFUeJzt3X+QVWX9B/Bn/cGKCksrwrICCqhYIjgZEKmkiSCVI0iNms1gOToYOCqJDU6KVramaQ5Fyh8NZCn+mAlNpqEUZJkScECJcSzGZSgwAZPa5ZeAwvnOOczul1WQzrLLc/fe12vmmcu993z2Hs6ePe/7nPPc55YlSZIEADjCjjrSLwgAKQEEQBQCCIAoBBAAUQggAKIQQABEIYAAiEIAARDFMaHA7N27N7zzzjuhU6dOoaysLPbqAJBTOr/B1q1bQ3V1dTjqqKPaTwCl4dOrV6/YqwHAYVq/fn3o2bNn+zkFl/Z8AGj/DnU8b7MAmjFjRjjttNPCcccdF4YOHRpeffXV/6nOaTeA4nCo43mbBNDTTz8dJk+eHKZNmxZee+21MGjQoDBq1Kjw7rvvtsXLAdAeJW1gyJAhycSJE5vu79mzJ6murk5qamoOWdvQ0JDOzq1pmqaF9t3S4/knafUe0O7du8OKFSvCiBEjmh5LR0Gk95csWfKx5Xft2hW2bNnSrAFQ/Fo9gN57772wZ8+e0L1792aPp/c3btz4seVrampCRUVFUzMCDqA0RB8FN3Xq1NDQ0NDU0mF7ABS/Vv8cUNeuXcPRRx8dNm3a1Ozx9H5VVdXHli8vL88aAKWl1XtAHTp0COedd15YsGBBs9kN0vvDhg1r7ZcDoJ1qk5kQ0iHY48ePD5/73OfCkCFDwiOPPBK2b98evvWtb7XFywHQDrVJAF111VXh3//+d7j77ruzgQfnnntumD9//scGJgBQusrSsdihgKTDsNPRcAC0b+nAss6dOxfuKDgASpMAAiAKAQRAFAIIgCgEEABRCCAAohBAAEQhgACIQgABEIUAAiAKAQRAFAIIgCgEEABRCCAAohBAAEQhgACIQgABEIUAAiAKAQRAFAIIgCgEEABRCCAAohBAAEQhgACIQgABEIUAAiAKAQRAFAIIgCgEEABRCCAAohBAAEQhgACIQgABEIUAAiAKAQRAFAIIgCgEEABRCCAAohBAAEQhgACIQgABEIUAAiAKAQRAFAIIgCgEEABRCCAAohBAAEQhgACIQgABEIUAAiAKAQRAFAIIgCiOifOyUJiOPvro3DUVFRWhUE2aNKlFdccff3zumv79++eumThxYu6an/70p7lrrrnmmtASO3fuzF1z//3356659957QynSAwIgCgEEQHEE0D333BPKysqatbPOOqu1XwaAdq5NrgGdffbZ4aWXXvr/FznGpSYAmmuTZEgDp6qqqi1+NABFok2uAb311luhuro69O3bN1x77bVh3bp1B112165dYcuWLc0aAMWv1QNo6NChYfbs2WH+/Pnh0UcfDWvXrg0XXnhh2Lp16wGXr6mpyYaxNrZevXq19ioBUAoBNHr06PD1r389DBw4MIwaNSr84Q9/CPX19eGZZ5454PJTp04NDQ0NTW39+vWtvUoAFKA2Hx3QpUuXcOaZZ4a6uroDPl9eXp41AEpLm38OaNu2bWHNmjWhR48ebf1SAJRyAN1+++2htrY2/OMf/wivvPJKGDt2bDa9SUunwgCgOLX6Kbi33347C5vNmzeHk08+OVxwwQVh6dKl2b8BoM0C6KmnnmrtH0mB6t27d+6aDh065K75whe+kLsmfePT0muWeY0bN65Fr1Vs0jefeU2fPj13TXpWJa+DjcI9lL/+9a+5a9IzQPxvzAUHQBQCCIAoBBAAUQggAKIQQABEIYAAiEIAARCFAAIgCgEEQBQCCIAoBBAAUQggAKIoS5IkCQVky5Yt2Vdzc+Sce+65LapbuHBh7hq/2/Zh7969uWu+/e1vt+j7wo6EDRs2tKjuv//9b+6a1atXt+i1ilH6LdedO3c+6PN6QABEIYAAiEIAARCFAAIgCgEEQBQCCIAoBBAAUQggAKIQQABEIYAAiEIAARCFAAIgCgEEQBTHxHlZCsm6detaVLd58+bcNWbD3mfZsmW5a+rr63PXXHzxxaEldu/enbvmN7/5TYtei9KlBwRAFAIIgCgEEABRCCAAohBAAEQhgACIQgABEIUAAiAKAQRAFAIIgCgEEABRCCAAojAZKeE///lPi+qmTJmSu+arX/1q7prXX389d8306dPDkbJy5crcNZdeemnumu3bt+euOfvss0NL3HLLLS2qgzz0gACIQgABEIUAAiAKAQRAFAIIgCgEEABRCCAAohBAAEQhgACIQgABEIUAAiAKAQRAFGVJkiShgGzZsiVUVFTEXg3aSOfOnXPXbN26NXfNzJkzQ0tcf/31uWu++c1v5q6ZM2dO7hpobxoaGj7xb14PCIAoBBAA7SOAFi9eHC6//PJQXV0dysrKwnPPPdfs+fSM3t133x169OgROnbsGEaMGBHeeuut1lxnAEoxgNIvxRo0aFCYMWPGAZ9/4IEHsi8De+yxx8KyZcvCCSecEEaNGhV27tzZGusLQKl+I+ro0aOzdiBp7+eRRx4J3//+98MVV1yRPfb444+H7t27Zz2lq6+++vDXGICi0KrXgNauXRs2btyYnXZrlI5oGzp0aFiyZMkBa3bt2pWNfNu/AVD8WjWA0vBJpT2e/aX3G5/7qJqamiykGluvXr1ac5UAKFDRR8FNnTo1Gyve2NavXx97lQBobwFUVVWV3W7atKnZ4+n9xuc+qry8PPug0v4NgOLXqgHUp0+fLGgWLFjQ9Fh6TScdDTds2LDWfCkASm0U3LZt20JdXV2zgQcrV64MlZWVoXfv3uHWW28NP/rRj8IZZ5yRBdJdd92VfWZozJgxrb3uAJRSAC1fvjxcfPHFTfcnT56c3Y4fPz7Mnj073HHHHdlnhW688cZQX18fLrjggjB//vxw3HHHte6aA9CumYyUovTggw+2qK7xDVUetbW1uWv2/6jC/2rv3r25ayAmk5ECUJAEEABRCCAAohBAAEQhgACIQgABEIUAAiAKAQRAFAIIgCgEEABRCCAAohBAAEQhgACIwmzYFKUTTjihRXUvvPBC7povfvGLuWtGjx6du+ZPf/pT7hqIyWzYABQkAQRAFAIIgCgEEABRCCAAohBAAEQhgACIQgABEIUAAiAKAQRAFAIIgCgEEABRmIwU9tOvX7/cNa+99lrumvr6+tw1L7/8cu6a5cuXh5aYMWNG7poCO5RQAExGCkBBEkAARCGAAIhCAAEQhQACIAoBBEAUAgiAKAQQAFEIIACiEEAARCGAAIhCAAEQhclI4TCNHTs2d82sWbNy13Tq1CkcKXfeeWfumscffzx3zYYNG3LX0H6YjBSAgiSAAIhCAAEQhQACIAoBBEAUAgiAKAQQAFEIIACiEEAARCGAAIhCAAEQhQACIAqTkUIEAwYMyF3z8MMP56655JJLwpEyc+bM3DX33Xdf7pp//etfuWuIw2SkABQkAQRA+wigxYsXh8svvzxUV1eHsrKy8NxzzzV7/rrrrsse379ddtllrbnOAJRiAG3fvj0MGjQozJgx46DLpIGTftFUY5szZ87hricAReaYvAWjR4/O2icpLy8PVVVVh7NeABS5NrkGtGjRotCtW7fQv3//cNNNN4XNmzcfdNldu3ZlI9/2bwAUv1YPoPT0W/rd8AsWLAg/+clPQm1tbdZj2rNnzwGXr6mpyYZdN7ZevXq19ioBUAyn4A7l6quvbvr3OeecEwYOHBj69euX9YoO9JmEqVOnhsmTJzfdT3tAQgig+LX5MOy+ffuGrl27hrq6uoNeL0o/qLR/A6D4tXkAvf3229k1oB49erT1SwFQzKfgtm3b1qw3s3bt2rBy5cpQWVmZtXvvvTeMGzcuGwW3Zs2acMcdd4TTTz89jBo1qrXXHYBSCqDly5eHiy++uOl+4/Wb8ePHh0cffTSsWrUq/PrXvw719fXZh1VHjhwZfvjDH2an2gCgkclIoZ3o0qVL7pp01pKWmDVrVu6adNaTvBYuXJi75tJLL81dQxwmIwWgIAkgAKIQQABEIYAAiEIAARCFAAIgCgEEQBQCCIAoBBAAUQggAKIQQABEIYAAiEIAARCF2bCBj9m1a1fummOOyf3tLuHDDz/MXdOS7xZbtGhR7hoOn9mwAShIAgiAKAQQAFEIIACiEEAARCGAAIhCAAEQhQACIAoBBEAUAgiAKAQQAFEIIACiyD97IHDYBg4cmLvma1/7Wu6awYMHh5ZoycSiLfHmm2/mrlm8eHGbrAtHnh4QAFEIIACiEEAARCGAAIhCAAEQhQACIAoBBEAUAgiAKAQQAFEIIACiEEAARCGAAIjCZKSwn/79++eumTRpUu6aK6+8MndNVVVVKGR79uzJXbNhw4bcNXv37s1dQ2HSAwIgCgEEQBQCCIAoBBAAUQggAKIQQABEIYAAiEIAARCFAAIgCgEEQBQCCIAoBBAAUZiMlILXkkk4r7nmmha9VksmFj3ttNNCsVm+fHnumvvuuy93ze9///vcNRQPPSAAohBAABR+ANXU1ITBgweHTp06hW7duoUxY8aE1atXN1tm586dYeLEieGkk04KJ554Yhg3blzYtGlTa683AKUUQLW1tVm4LF26NLz44ovhgw8+CCNHjgzbt29vWua2224LL7zwQnj22Wez5d95550WffkWAMUt1yCE+fPnN7s/e/bsrCe0YsWKMHz48NDQ0BB+9atfhSeffDJ86UtfypaZNWtW+PSnP52F1uc///nWXXsASvMaUBo4qcrKyuw2DaK0VzRixIimZc4666zQu3fvsGTJkgP+jF27doUtW7Y0awAUvxYHUPq97Lfeems4//zzw4ABA7LHNm7cGDp06BC6dOnSbNnu3btnzx3sulJFRUVT69WrV0tXCYBSCKD0WtAbb7wRnnrqqcNagalTp2Y9qca2fv36w/p5ABTxB1HTD+vNmzcvLF68OPTs2bPZBwZ3794d6uvrm/WC0lFwB/swYXl5edYAKC25ekBJkmThM3fu3LBw4cLQp0+fZs+fd9554dhjjw0LFixoeiwdpr1u3bowbNiw1ltrAEqrB5SedktHuD3//PPZZ4Ear+uk1246duyY3V5//fVh8uTJ2cCEzp07h5tvvjkLHyPgAGhxAD366KPZ7UUXXdTs8XSo9XXXXZf9+2c/+1k46qijsg+gpiPcRo0aFX75y1/meRkASkBZkp5XKyDpMOy0J0XhS0c35vWZz3wmd80vfvGL3DXp8P9is2zZstw1Dz74YIteKz3L0ZKRsbC/dGBZeibsYMwFB0AUAgiAKAQQAFEIIACiEEAARCGAAIhCAAEQhQACIAoBBEAUAgiAKAQQAFEIIACiEEAAtJ9vRKVwpd/DlNfMmTNb9Frnnntu7pq+ffuGYvPKK6/krnnooYdy1/zxj3/MXfP+++/nroEjRQ8IgCgEEABRCCAAohBAAEQhgACIQgABEIUAAiAKAQRAFAIIgCgEEABRCCAAohBAAERhMtIjZOjQoblrpkyZkrtmyJAhuWtOOeWUUGx27NjRorrp06fnrvnxj3+cu2b79u25a6DY6AEBEIUAAiAKAQRAFAIIgCgEEABRCCAAohBAAEQhgACIQgABEIUAAiAKAQRAFAIIgChMRnqEjB079ojUHElvvvlm7pp58+blrvnwww9z1zz00EOhJerr61tUB+SnBwRAFAIIgCgEEABRCCAAohBAAEQhgACIQgABEIUAAiAKAQRAFAIIgCgEEABRCCAAoihLkiQJBWTLli2hoqIi9moAcJgaGhpC586dD/q8HhAAUQggAAo/gGpqasLgwYNDp06dQrdu3cKYMWPC6tWrmy1z0UUXhbKysmZtwoQJrb3eAJRSANXW1oaJEyeGpUuXhhdffDF88MEHYeTIkWH79u3NlrvhhhvChg0bmtoDDzzQ2usNQCl9I+r8+fOb3Z89e3bWE1qxYkUYPnx40+PHH398qKqqar21BKDoHHW4IxxSlZWVzR5/4oknQteuXcOAAQPC1KlTw44dOw76M3bt2pWNfNu/AVACkhbas2dP8pWvfCU5//zzmz0+c+bMZP78+cmqVauS3/72t8kpp5ySjB079qA/Z9q0aekwcE3TNC0UV2toaPjEHGlxAE2YMCE59dRTk/Xr13/icgsWLMhWpK6u7oDP79y5M1vJxpb+vNgbTdM0TQttHkC5rgE1mjRpUpg3b15YvHhx6Nmz5ycuO3To0Oy2rq4u9OvX72PPl5eXZw2A0pIrgNIe08033xzmzp0bFi1aFPr06XPImpUrV2a3PXr0aPlaAlDaAZQOwX7yySfD888/n30WaOPGjdnj6dQ5HTt2DGvWrMme//KXvxxOOumksGrVqnDbbbdlI+QGDhzYVv8HANqjPNd9Dnaeb9asWdnz69atS4YPH55UVlYm5eXlyemnn55MmTLlkOcB95cuG/u8paZpmhYOux3q2G8yUgDahMlIAShIAgiAKAQQAFEIIACiEEAARCGAAIhCAAEQhQACIAoBBEAUAgiAKAQQAFEIIACiEEAARCGAAIhCAAEQhQACIAoBBEAUAgiAKAQQAFEIIACiEEAARCGAAIhCAAEQhQACIAoBBEAUBRdASZLEXgUAjsDxvOACaOvWrbFXAYAjcDwvSwqsy7F3797wzjvvhE6dOoWysrJmz23ZsiX06tUrrF+/PnTu3DmUKtthH9thH9thH9uhcLZDGitp+FRXV4ejjjp4P+eYUGDSle3Zs+cnLpNu1FLewRrZDvvYDvvYDvvYDoWxHSoqKg65TMGdggOgNAggAKJoVwFUXl4epk2blt2WMtthH9thH9thH9uh/W2HghuEAEBpaFc9IACKhwACIAoBBEAUAgiAKNpNAM2YMSOcdtpp4bjjjgtDhw4Nr776aig199xzTzY7xP7trLPOCsVu8eLF4fLLL88+VZ3+n5977rlmz6fjaO6+++7Qo0eP0LFjxzBixIjw1ltvhVLbDtddd93H9o/LLrssFJOampowePDgbKaUbt26hTFjxoTVq1c3W2bnzp1h4sSJ4aSTTgonnnhiGDduXNi0aVMote1w0UUXfWx/mDBhQigk7SKAnn766TB58uRsaOFrr70WBg0aFEaNGhXefffdUGrOPvvssGHDhqb25z//ORS77du3Z7/z9E3IgTzwwANh+vTp4bHHHgvLli0LJ5xwQrZ/pAeiUtoOqTRw9t8/5syZE4pJbW1tFi5Lly4NL774Yvjggw/CyJEjs23T6LbbbgsvvPBCePbZZ7Pl06m9rrzyylBq2yF1ww03NNsf0r+VgpK0A0OGDEkmTpzYdH/Pnj1JdXV1UlNTk5SSadOmJYMGDUpKWbrLzp07t+n+3r17k6qqquTBBx9seqy+vj4pLy9P5syZk5TKdkiNHz8+ueKKK5JS8u6772bbora2tul3f+yxxybPPvts0zJ/+9vfsmWWLFmSlMp2SH3xi19MbrnllqSQFXwPaPfu3WHFihXZaZX954tL7y9ZsiSUmvTUUnoKpm/fvuHaa68N69atC6Vs7dq1YePGjc32j3QOqvQ0bSnuH4sWLcpOyfTv3z/cdNNNYfPmzaGYNTQ0ZLeVlZXZbXqsSHsD++8P6Wnq3r17F/X+0PCR7dDoiSeeCF27dg0DBgwIU6dODTt27AiFpOAmI/2o9957L+zZsyd079692ePp/b///e+hlKQH1dmzZ2cHl7Q7fe+994YLL7wwvPHGG9m54FKUhk/qQPtH43OlIj39lp5q6tOnT1izZk248847w+jRo7MD79FHHx2KTTpz/q233hrOP//87ACbSn/nHTp0CF26dCmZ/WHvAbZD6hvf+EY49dRTszesq1atCt/73vey60S/+93vQqEo+ADi/6UHk0YDBw7MAindwZ555plw/fXXR1034rv66qub/n3OOedk+0i/fv2yXtEll1wSik16DSR981UK10Fbsh1uvPHGZvtDOkgn3Q/SNyfpflEICv4UXNp9TN+9fXQUS3q/qqoqlLL0Xd6ZZ54Z6urqQqlq3AfsHx+XnqZN/36Kcf+YNGlSmDdvXnj55ZebfX1L+jtPT9vX19eXxP4w6SDb4UDSN6ypQtofCj6A0u70eeedFxYsWNCsy5neHzZsWChl27Zty97NpO9sSlV6uik9sOy/f6RfyJWOhiv1/ePtt9/OrgEV0/6Rjr9ID7pz584NCxcuzH7/+0uPFccee2yz/SE97ZReKy2m/SE5xHY4kJUrV2a3BbU/JO3AU089lY1qmj17dvLmm28mN954Y9KlS5dk48aNSSn57ne/myxatChZu3Zt8pe//CUZMWJE0rVr12wETDHbunVr8vrrr2ct3WUffvjh7N///Oc/s+fvv//+bH94/vnnk1WrVmUjwfr06ZO8//77Salsh/S522+/PRvple4fL730UvLZz342OeOMM5KdO3cmxeKmm25KKioqsr+DDRs2NLUdO3Y0LTNhwoSkd+/eycKFC5Ply5cnw4YNy1oxuekQ26Guri75wQ9+kP3/0/0h/dvo27dvMnz48KSQtIsASv385z/PdqoOHTpkw7KXLl2alJqrrroq6dGjR7YNTjnllOx+uqMVu5dffjk74H60pcOOG4di33XXXUn37t2zNyqXXHJJsnr16qSUtkN64Bk5cmRy8sknZ8OQTz311OSGG24oujdpB/r/p23WrFlNy6RvPL7zne8kn/rUp5Ljjz8+GTt2bHZwLqXtsG7duixsKisrs7+J008/PZkyZUrS0NCQFBJfxwBAFAV/DQiA4iSAAIhCAAEQhQACIAoBBEAUAgiAKAQQAFEIIACiEEAARCGAAIhCAAEQhQACIMTwfwuo74MNPBzYAAAAAElFTkSuQmCC"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 12
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-21T02:27:16.653943Z",
     "start_time": "2025-08-21T02:27:16.642839Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from torch.utils.data import DataLoader\n",
    "\n",
    "train_loader = DataLoader(train_dataset, batch_size=16, shuffle=True)\n",
    "test_loader = DataLoader(test_dataset, batch_size=16, shuffle=False)\n",
    "\n",
    "for images, labels in train_loader:\n",
    "    print(images.shape)\n",
    "    print(labels.shape)\n",
    "    break"
   ],
   "id": "80b7452499e35425",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.Size([16, 1, 28, 28])\n",
      "torch.Size([16])\n"
     ]
    }
   ],
   "execution_count": 17
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "定义模型",
   "id": "8bc14eb7f032e7bc"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-21T02:27:21.213629Z",
     "start_time": "2025-08-21T02:27:21.205475Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from torch import nn\n",
    "import torch\n",
    "# 大都督周瑜（我的微信: it_zhouyu）\n",
    "\n",
    "class MnistModel(nn.Module):\n",
    "    def __init__(self):\n",
    "        super().__init__()\n",
    "\n",
    "        # 1*28*28\n",
    "        # 28-5+1=24，16表示16个卷积核，每个卷积核的大小为5*5，每个卷积核会提取出图片中不同的特征, 输出16张24*24的图片\n",
    "        self.conv1 = nn.Conv2d(in_channels=1, out_channels=16, kernel_size=5)\n",
    "\n",
    "        # 24/2=12，MaxPool2d就是取卷积核中的最大值, 输出16张12*12的图片\n",
    "        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)\n",
    "\n",
    "        # 12-5+1=8, 输出32张8*8的图片\n",
    "        self.conv2 = nn.Conv2d(16, 32, kernel_size=5)\n",
    "        # 8/2=4，最后输出的图片大小为4*4, 输出32张4*4的图片  32*4*4\n",
    "        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)\n",
    "\n",
    "        self.fc1 = nn.Linear(32 * 4 * 4, 128)\n",
    "        self.fc2 = nn.Linear(128, 10)\n",
    "\n",
    "    def forward(self, x):\n",
    "        x = torch.relu(self.conv1(x))\n",
    "        x = self.pool1(x)\n",
    "        x = torch.relu(self.conv2(x))\n",
    "        x = self.pool2(x)\n",
    "        x = x.view(-1, 32 * 4 * 4)\n",
    "        x = torch.relu(self.fc1(x))\n",
    "        x = self.fc2(x)\n",
    "        return x"
   ],
   "id": "9ad34aa4f7d8d743",
   "outputs": [],
   "execution_count": 21
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-21T02:30:49.651184Z",
     "start_time": "2025-08-21T02:30:20.678793Z"
    }
   },
   "cell_type": "code",
   "source": [
    "model = MnistModel()\n",
    "\n",
    "optimizer = torch.optim.SGD(model.parameters(), lr=0.1)\n",
    "criterion = nn.CrossEntropyLoss()\n",
    "\n",
    "epochs = 2\n",
    "for epoch in range(epochs):\n",
    "    for i, (images, labels) in enumerate(train_loader):\n",
    "        outputs = model(images)\n",
    "        loss = criterion(outputs, labels)\n",
    "\n",
    "        optimizer.zero_grad()\n",
    "        loss.backward()\n",
    "        optimizer.step()\n",
    "\n",
    "        if (i + 1) % 100 == 0:\n",
    "            print('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}'\n",
    "                  .format(epoch + 1, epochs, i + 1, len(train_loader), loss.item()))"
   ],
   "id": "8866b928c08b225d",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch [1/2], Step [100/3750], Loss: 0.9576\n",
      "Epoch [1/2], Step [200/3750], Loss: 0.1411\n",
      "Epoch [1/2], Step [300/3750], Loss: 0.4731\n",
      "Epoch [1/2], Step [400/3750], Loss: 0.2108\n",
      "Epoch [1/2], Step [500/3750], Loss: 0.0509\n",
      "Epoch [1/2], Step [600/3750], Loss: 0.2323\n",
      "Epoch [1/2], Step [700/3750], Loss: 0.2045\n",
      "Epoch [1/2], Step [800/3750], Loss: 0.1506\n",
      "Epoch [1/2], Step [900/3750], Loss: 0.0098\n",
      "Epoch [1/2], Step [1000/3750], Loss: 0.1704\n",
      "Epoch [1/2], Step [1100/3750], Loss: 0.0046\n",
      "Epoch [1/2], Step [1200/3750], Loss: 0.0042\n",
      "Epoch [1/2], Step [1300/3750], Loss: 0.0789\n",
      "Epoch [1/2], Step [1400/3750], Loss: 0.6476\n",
      "Epoch [1/2], Step [1500/3750], Loss: 0.0695\n",
      "Epoch [1/2], Step [1600/3750], Loss: 0.0979\n",
      "Epoch [1/2], Step [1700/3750], Loss: 0.0887\n",
      "Epoch [1/2], Step [1800/3750], Loss: 0.0832\n",
      "Epoch [1/2], Step [1900/3750], Loss: 0.0502\n",
      "Epoch [1/2], Step [2000/3750], Loss: 0.0231\n",
      "Epoch [1/2], Step [2100/3750], Loss: 0.0346\n",
      "Epoch [1/2], Step [2200/3750], Loss: 0.0076\n",
      "Epoch [1/2], Step [2300/3750], Loss: 0.0600\n",
      "Epoch [1/2], Step [2400/3750], Loss: 0.0466\n",
      "Epoch [1/2], Step [2500/3750], Loss: 0.0341\n",
      "Epoch [1/2], Step [2600/3750], Loss: 0.0039\n",
      "Epoch [1/2], Step [2700/3750], Loss: 0.0316\n",
      "Epoch [1/2], Step [2800/3750], Loss: 0.0106\n",
      "Epoch [1/2], Step [2900/3750], Loss: 0.7437\n",
      "Epoch [1/2], Step [3000/3750], Loss: 0.0141\n",
      "Epoch [1/2], Step [3100/3750], Loss: 0.0313\n",
      "Epoch [1/2], Step [3200/3750], Loss: 0.0702\n",
      "Epoch [1/2], Step [3300/3750], Loss: 0.0398\n",
      "Epoch [1/2], Step [3400/3750], Loss: 0.0196\n",
      "Epoch [1/2], Step [3500/3750], Loss: 0.0170\n",
      "Epoch [1/2], Step [3600/3750], Loss: 0.0085\n",
      "Epoch [1/2], Step [3700/3750], Loss: 0.0032\n",
      "Epoch [2/2], Step [100/3750], Loss: 0.0004\n",
      "Epoch [2/2], Step [200/3750], Loss: 0.0005\n",
      "Epoch [2/2], Step [300/3750], Loss: 0.0507\n",
      "Epoch [2/2], Step [400/3750], Loss: 0.0016\n",
      "Epoch [2/2], Step [500/3750], Loss: 0.2550\n",
      "Epoch [2/2], Step [600/3750], Loss: 0.0575\n",
      "Epoch [2/2], Step [700/3750], Loss: 0.0007\n",
      "Epoch [2/2], Step [800/3750], Loss: 0.0456\n",
      "Epoch [2/2], Step [900/3750], Loss: 0.0321\n",
      "Epoch [2/2], Step [1000/3750], Loss: 0.0091\n",
      "Epoch [2/2], Step [1100/3750], Loss: 0.0588\n",
      "Epoch [2/2], Step [1200/3750], Loss: 0.2209\n",
      "Epoch [2/2], Step [1300/3750], Loss: 0.3675\n",
      "Epoch [2/2], Step [1400/3750], Loss: 0.0513\n",
      "Epoch [2/2], Step [1500/3750], Loss: 0.0014\n",
      "Epoch [2/2], Step [1600/3750], Loss: 0.0034\n",
      "Epoch [2/2], Step [1700/3750], Loss: 0.2738\n",
      "Epoch [2/2], Step [1800/3750], Loss: 0.1154\n",
      "Epoch [2/2], Step [1900/3750], Loss: 0.0066\n",
      "Epoch [2/2], Step [2000/3750], Loss: 0.0021\n",
      "Epoch [2/2], Step [2100/3750], Loss: 0.0437\n",
      "Epoch [2/2], Step [2200/3750], Loss: 0.0002\n",
      "Epoch [2/2], Step [2300/3750], Loss: 0.2472\n",
      "Epoch [2/2], Step [2400/3750], Loss: 0.1583\n",
      "Epoch [2/2], Step [2500/3750], Loss: 0.4348\n",
      "Epoch [2/2], Step [2600/3750], Loss: 0.0056\n",
      "Epoch [2/2], Step [2700/3750], Loss: 0.0046\n",
      "Epoch [2/2], Step [2800/3750], Loss: 0.0002\n",
      "Epoch [2/2], Step [2900/3750], Loss: 0.0085\n",
      "Epoch [2/2], Step [3000/3750], Loss: 0.0242\n",
      "Epoch [2/2], Step [3100/3750], Loss: 0.0206\n",
      "Epoch [2/2], Step [3200/3750], Loss: 0.0131\n",
      "Epoch [2/2], Step [3300/3750], Loss: 0.0030\n",
      "Epoch [2/2], Step [3400/3750], Loss: 0.0004\n",
      "Epoch [2/2], Step [3500/3750], Loss: 0.0010\n",
      "Epoch [2/2], Step [3600/3750], Loss: 0.0103\n",
      "Epoch [2/2], Step [3700/3750], Loss: 0.0002\n"
     ]
    }
   ],
   "execution_count": 24
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-21T02:32:27.862546Z",
     "start_time": "2025-08-21T02:32:27.767623Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 开始测试\n",
    "test_loader = DataLoader(test_dataset, batch_size=1, shuffle=False)\n",
    "plt.imshow(test_dataset[0][0].view(-1, 28), cmap='gray')"
   ],
   "id": "928fc30bdc060a0",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x1547f1f00>"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ],
      "image/png": "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999vy30GoBIDaOfOnTFs2LCYPXv2QV+fNWtWPPzww/Hoo4/GW2+9FUcffXSMGzeuVeeUAShfJQ9CuPzyy4tyMHnv56GHHoq77747rrrqquK5xx9/PPr161f0lK677rpvvscAlIU2vQa0bt262LJlS3HabZ+ampoYMWJELFmy5KB1du/eHU1NTS0KAOWvTQMoD59c3uPZX76877Uva2hoKEJqX6mvr2/LXQKgg0o+Cm7GjBnR2NjYXDZs2JB6lwDobAFUW1tbPG7durXF8/nyvte+rLq6Onr27NmiAFD+2jSABg8eXATN/nfW59d08tFwI0eObMtNAVBpo+B27NgRa9asaTHwYMWKFcX0GAMHDoxp06bFL37xizj55JOLQJo5c2Zxz9D48ePbet8BqKQAWrZsWVxyySXNy9OnTy8eJ06cGHPnzo0777yzuFdoypQpsW3btrjggguK+b+OPPLItt1zADq1qiy/eacDyU/Z5aPhgM5lwoQJJdd59tlnS66zatWqkuvs/6G5FJ988kmr6vGFfGDZV13XTz4KDoDKJIAASEIAAZCEAAIgCQEEQBICCIAkBBAASQggAJIQQAAkIYAASEIAAZCEAAIgCQEEQOf4Ogag/PXt27fkOo888kjJdY44ovTPwA888EDJdcxq3THpAQGQhAACIAkBBEASAgiAJAQQAEkIIACSEEAAJCGAAEhCAAGQhAACIAkBBEASAgiAJExGChxg6tSpJdc5/vjjS67z73//u+Q6q1evLrkOHZMeEABJCCAAkhBAACQhgABIQgABkIQAAiAJAQRAEgIIgCQEEABJCCAAkhBAACQhgABIwmSkUMZGjRrVqno//elP43AYP358yXVWrVrVLvvC4acHBEASAgiAJAQQAEkIIACSEEAAJCGAAEhCAAGQhAACIAkBBEASAgiAJAQQAEkIIACSMBkplLErrriiVfW6du1acp0FCxaUXGfJkiUl16F86AEBkIQAAqBzBNDixYvjyiuvjLq6uqiqqooXXnihxeuTJk0qnt+/XHbZZW25zwBUYgDt3Lkzhg0bFrNnzz7kOnngbN68ubk89dRT33Q/Aaj0QQiXX355Ub5KdXV11NbWfpP9AqDMtcs1oIULF0bfvn3j1FNPjZtvvjk+/vjjQ667e/fuaGpqalEAKH9tHkD56bfHH3+8GJL5q1/9KhYtWlT0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"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 30
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-21T02:32:29.351036Z",
     "start_time": "2025-08-21T02:32:29.342989Z"
    }
   },
   "cell_type": "code",
   "source": [
    "with torch.no_grad():\n",
    "    for images, labels in test_loader:\n",
    "        outputs = model(images)  # 形状是16 * 10\n",
    "\n",
    "        _, indices = torch.max(outputs.data, 1)\n",
    "\n",
    "        print('预测结果为: {}'.format(indices[0]))\n",
    "        break\n"
   ],
   "id": "cad3949e75f58bb4",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "预测结果为: 7\n"
     ]
    }
   ],
   "execution_count": 31
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-21T02:32:33.151130Z",
     "start_time": "2025-08-21T02:32:32.578436Z"
    }
   },
   "cell_type": "code",
   "source": [
    "test_image = test_dataset[0][0]\n",
    "test_image = test_image.unsqueeze(0)\n",
    "with torch.no_grad():\n",
    "    conv1_output = model.conv1(test_image)\n",
    "\n",
    "feature_maps = conv1_output[0]\n",
    "feature_maps = feature_maps.cpu().numpy()\n",
    "\n",
    "# 绘图：4x4 网格显示 16 个特征图\n",
    "fig, axes = plt.subplots(4, 4, figsize=(8, 8))\n",
    "for i in range(16):\n",
    "    row = i // 4\n",
    "    col = i % 4\n",
    "    axes[row][col].imshow(feature_maps[i], cmap='gray')\n",
    "\n",
    "plt.show()"
   ],
   "id": "667a0de634cf310",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Figure size 800x800 with 16 Axes>"
      ],
      "image/png": "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+/fvd04Ma8lgKU2n9VCPg0yqQ63etJSs5OzZs+J4S0uL88/TxqWUpVaHUs3FeZcD6lCuIauqqso39tVXXznXhZQit+wiyrVfupYulhLx/frFcwOWv/zlL112eUhyDXbX01w7x0l1qNWyVAP19fXi3M4L+c5ycnKc32v79OljMsUNXaPZvk1E+1Y5trjtb1Rz587tspVPaWmpqaysVN8w7bY8nW9AENQhooA6RBJq0KIOEYmFpv3NYvny5WbOnDkde5vV1NR4n2Zcu6ovLCz0/p12nZPdq6r9pu0nCUioQ0QBdYik1KBFHSISC017XYjdgPf111+/oTuwcuVK77ew9pv0UTegoQ4RBdQhklKDFnWIdLquC1OWLVtm3n33XbN161YzZsyYjvGioiJvZ3t7DUzn36Ds9Yv230nsrvlBds4H2lGHiALqEEmqQYs6RK8tNG0ru8cee8ysX7/evP/++6asrKzLv58xY4YXDti4caO3hYJlt1o4fvy4KS8vN3Eitdbr7qLjuro635j25wapJaR2DYy2DYXU5k9rl5Wbm5uollbUof78SRfLa23NpACFNldrY2m3TLmW9gaVtHZ+mVSHWos/KVhj7d271zd27Ngx54CPvYbQ9dyp0c6p0msnrsEMW4N2kZkJNdhdCFJr9yyFDbXzk/S9g16bKn3vbwIEKeP8vpy2hab9aN6m195++21v3672azzsAsf25Lb//OlPf2pWrFjhXYxsF0P2RGwLOm7pNkQXdYgooA7R237xi1+YN998kxpEchaav//9771/3nPPPV3G7XYJP/7xj73///zzz3urcvvbk/0NYf78+ebll19O531GhqMOEQXUIXqb3brIogaRqD+dfxv7p401a9Z4NyAM1CGigDpEb7NBHekyqs6oQfS2ZF4QAAAAgF7HQhMAAAChiGffrR5w/vx5cVzbT0xKm2mJYZv4c037Hj58WBwvLi72jQ0dOjQj0r6ZRGvnqLVulNLB2jYm0o4GX375pXNrNa29qZbqjGuyF/plAu2daFzOce3dalx2yxg3blygXThOnTrlfP6Nc9vTTKe1FdXqc8SIEc7nVClhbgNVrrttaLslDFB+XlIT5pLMOVIAAAD0KBaaAAAACAULTQAAAISChSYAAABCQRhIce7cuUAt16QLe7ULl6Xvcfr06UAtt6QLjLUwEOJLah/aXbBC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"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 32
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-21T02:33:23.873826Z",
     "start_time": "2025-08-21T02:33:20.339193Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 开始测试\n",
    "correct = 0\n",
    "total = 0\n",
    "with torch.no_grad():\n",
    "    for images, labels in test_loader:\n",
    "        outputs = model(images)  # 形状是16 * 10\n",
    "\n",
    "        _, indices = torch.max(outputs.data, 1)\n",
    "\n",
    "        total += labels.size(0)  # (16,10) 记录总测试样本个数\n",
    "\n",
    "        matches = (indices == labels)\n",
    "        correct += matches.sum().item()\n",
    "\n",
    "print('测试集正确率为: {} %'.format(100 * correct / total))"
   ],
   "id": "6374780fd056c48d",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "测试集正确率为: 98.21 %\n"
     ]
    }
   ],
   "execution_count": 33
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "## ResNet和ImageNet\n",
    "\n",
    "ResNet，Residual Network，是一个用于图像识别的残差神经网络，何凯明\n",
    "ResNet论文：https://arxiv.org/abs/1512.03385\n",
    "\n",
    "ImageNet是一个用于识别图像的计算机视觉数据集，李飞飞\n",
    "ImageNet官网：https://www.image-net.org/"
   ],
   "id": "c5636dccfa6ef1b9"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-21T02:37:08.377326Z",
     "start_time": "2025-08-21T02:37:04.639446Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from transformers import AutoModelForImageClassification\n",
    "import os\n",
    "\n",
    "# 设置环境变量\n",
    "os.environ[\"HF_ENDPOINT\"] = \"https://hf-mirror.com\"\n",
    "os.environ[\"HF_HUB_ENABLE_HF_TRANSFER\"] = \"1\"  # 启用高速下载\n",
    "\n",
    "model = AutoModelForImageClassification.from_pretrained(\"microsoft/resnet-18\")"
   ],
   "id": "7519e2e3d963baf2",
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
      "  from .autonotebook import tqdm as notebook_tqdm\n"
     ]
    }
   ],
   "execution_count": 34
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-21T02:37:39.405410Z",
     "start_time": "2025-08-21T02:37:39.398851Z"
    }
   },
   "cell_type": "code",
   "source": "print(model)",
   "id": "479895c87aabfa4f",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ResNetForImageClassification(\n",
      "  (resnet): ResNetModel(\n",
      "    (embedder): ResNetEmbeddings(\n",
      "      (embedder): ResNetConvLayer(\n",
      "        (convolution): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)\n",
      "        (normalization): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "        (activation): ReLU()\n",
      "      )\n",
      "      (pooler): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)\n",
      "    )\n",
      "    (encoder): ResNetEncoder(\n",
      "      (stages): ModuleList(\n",
      "        (0): ResNetStage(\n",
      "          (layers): Sequential(\n",
      "            (0): ResNetBasicLayer(\n",
      "              (shortcut): Identity()\n",
      "              (layer): Sequential(\n",
      "                (0): ResNetConvLayer(\n",
      "                  (convolution): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "                  (normalization): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "                  (activation): ReLU()\n",
      "                )\n",
      "                (1): ResNetConvLayer(\n",
      "                  (convolution): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "                  (normalization): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "                  (activation): Identity()\n",
      "                )\n",
      "              )\n",
      "              (activation): ReLU()\n",
      "            )\n",
      "            (1): ResNetBasicLayer(\n",
      "              (shortcut): Identity()\n",
      "              (layer): Sequential(\n",
      "                (0): ResNetConvLayer(\n",
      "                  (convolution): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "                  (normalization): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "                  (activation): ReLU()\n",
      "                )\n",
      "                (1): ResNetConvLayer(\n",
      "                  (convolution): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "                  (normalization): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "                  (activation): Identity()\n",
      "                )\n",
      "              )\n",
      "              (activation): ReLU()\n",
      "            )\n",
      "          )\n",
      "        )\n",
      "        (1): ResNetStage(\n",
      "          (layers): Sequential(\n",
      "            (0): ResNetBasicLayer(\n",
      "              (shortcut): ResNetShortCut(\n",
      "                (convolution): Conv2d(64, 128, kernel_size=(1, 1), stride=(2, 2), bias=False)\n",
      "                (normalization): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "              )\n",
      "              (layer): Sequential(\n",
      "                (0): ResNetConvLayer(\n",
      "                  (convolution): Conv2d(64, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)\n",
      "                  (normalization): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "                  (activation): ReLU()\n",
      "                )\n",
      "                (1): ResNetConvLayer(\n",
      "                  (convolution): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "                  (normalization): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "                  (activation): Identity()\n",
      "                )\n",
      "              )\n",
      "              (activation): ReLU()\n",
      "            )\n",
      "            (1): ResNetBasicLayer(\n",
      "              (shortcut): Identity()\n",
      "              (layer): Sequential(\n",
      "                (0): ResNetConvLayer(\n",
      "                  (convolution): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "                  (normalization): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "                  (activation): ReLU()\n",
      "                )\n",
      "                (1): ResNetConvLayer(\n",
      "                  (convolution): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "                  (normalization): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "                  (activation): Identity()\n",
      "                )\n",
      "              )\n",
      "              (activation): ReLU()\n",
      "            )\n",
      "          )\n",
      "        )\n",
      "        (2): ResNetStage(\n",
      "          (layers): Sequential(\n",
      "            (0): ResNetBasicLayer(\n",
      "              (shortcut): ResNetShortCut(\n",
      "                (convolution): Conv2d(128, 256, kernel_size=(1, 1), stride=(2, 2), bias=False)\n",
      "                (normalization): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "              )\n",
      "              (layer): Sequential(\n",
      "                (0): ResNetConvLayer(\n",
      "                  (convolution): Conv2d(128, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)\n",
      "                  (normalization): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "                  (activation): ReLU()\n",
      "                )\n",
      "                (1): ResNetConvLayer(\n",
      "                  (convolution): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "                  (normalization): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "                  (activation): Identity()\n",
      "                )\n",
      "              )\n",
      "              (activation): ReLU()\n",
      "            )\n",
      "            (1): ResNetBasicLayer(\n",
      "              (shortcut): Identity()\n",
      "              (layer): Sequential(\n",
      "                (0): ResNetConvLayer(\n",
      "                  (convolution): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "                  (normalization): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "                  (activation): ReLU()\n",
      "                )\n",
      "                (1): ResNetConvLayer(\n",
      "                  (convolution): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "                  (normalization): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "                  (activation): Identity()\n",
      "                )\n",
      "              )\n",
      "              (activation): ReLU()\n",
      "            )\n",
      "          )\n",
      "        )\n",
      "        (3): ResNetStage(\n",
      "          (layers): Sequential(\n",
      "            (0): ResNetBasicLayer(\n",
      "              (shortcut): ResNetShortCut(\n",
      "                (convolution): Conv2d(256, 512, kernel_size=(1, 1), stride=(2, 2), bias=False)\n",
      "                (normalization): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "              )\n",
      "              (layer): Sequential(\n",
      "                (0): ResNetConvLayer(\n",
      "                  (convolution): Conv2d(256, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)\n",
      "                  (normalization): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "                  (activation): ReLU()\n",
      "                )\n",
      "                (1): ResNetConvLayer(\n",
      "                  (convolution): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "                  (normalization): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "                  (activation): Identity()\n",
      "                )\n",
      "              )\n",
      "              (activation): ReLU()\n",
      "            )\n",
      "            (1): ResNetBasicLayer(\n",
      "              (shortcut): Identity()\n",
      "              (layer): Sequential(\n",
      "                (0): ResNetConvLayer(\n",
      "                  (convolution): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "                  (normalization): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "                  (activation): ReLU()\n",
      "                )\n",
      "                (1): ResNetConvLayer(\n",
      "                  (convolution): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "                  (normalization): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "                  (activation): Identity()\n",
      "                )\n",
      "              )\n",
      "              (activation): ReLU()\n",
      "            )\n",
      "          )\n",
      "        )\n",
      "      )\n",
      "    )\n",
      "    (pooler): AdaptiveAvgPool2d(output_size=(1, 1))\n",
      "  )\n",
      "  (classifier): Sequential(\n",
      "    (0): Flatten(start_dim=1, end_dim=-1)\n",
      "    (1): Linear(in_features=512, out_features=1000, bias=True)\n",
      "  )\n",
      ")\n"
     ]
    }
   ],
   "execution_count": 35
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "有17个ResNetConvLayer，加上最后一个线性分类层，层越多模型越强大",
   "id": "8e7a23cd18abbb99"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.20"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
